package com.xyhy.core.file.utils;

//import org.springframework.mock.web.MockMultipartFile;

import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.regex.Pattern;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

/**
 * @author robert
 * @since 2024-10-10
 */
public class FileUtils {
  private static int CAPACITY = 8192;// 单次读取流的大小

  /**
   * 获取二进制的MD5
   *
   * @param bytes 二进制数据
   * @return md5字符串
   */
  public static String getMd5(byte[] bytes) {
    BigInteger bi = null;
    MessageDigest md;
    try {
      md = MessageDigest.getInstance("MD5");
      md.update(bytes);
      byte[] b = md.digest();
      bi = new BigInteger(1, b);
      return bi.toString(16);
    } catch (NoSuchAlgorithmException e) {
      return null;
    }
  }

  /**
   * 通过输入流计算文件md5
   *
   * @param in 输入流
   * @return md5码
   */
  public static String getMd5(InputStream in) {
    MessageDigest md;
    try {
      md = MessageDigest.getInstance("MD5");
      byte[] buffer = new byte[CAPACITY];
      in.read(buffer);
      int length = 0;
      while ((length = in.read(buffer)) != -1) {
        md.update(buffer, 0, length);
      }
      byte[] b = md.digest();
      BigInteger bi = new BigInteger(1, b);
      return bi.toString(16);
    } catch (Exception e) {
      return null;
    } finally {
      if (in != null) {
        try {
          in.close();
        } catch (IOException e) {
        }
      }
    }
  }

  /**
   * 获取multipartFile的MD5值
   *
   * @param multipartFile 上传的文件
   * @return md5码
   */
  public static String getMd5(MultipartFile multipartFile) {
    if (multipartFile == null) {
      return null;
    }
    MessageDigest md;
    InputStream in = null;
    try {
      md = MessageDigest.getInstance("MD5");
      in = multipartFile.getInputStream();
      byte[] buffer = new byte[CAPACITY];
      in.read(buffer);
      int length = 0;
      while ((length = in.read(buffer)) != -1) {
        md.update(buffer, 0, length);
      }
      byte[] b = md.digest();
      BigInteger bi = new BigInteger(1, b);
      return bi.toString(16);
    } catch (Exception e) {
      return null;
    } finally {
      if (in != null) {
        try {
          in.close();
        } catch (IOException e) {
        }
      }
    }
  }

  /**
   * 文件名合法性校验
   *
   * @param fileName 文件名
   * @return 是否合法
   */
  public static boolean isValidFileName(String fileName) {
    if (fileName == null || fileName.length() > 50 || fileName.contains("\\") || fileName.contains("/")) {
      return false;
    } else {
      return fileName.matches(
              "[^\\s\\\\/:\\*\\?\\\"<>\\|](\\x20|[^\\s\\\\/:\\*\\?\\\"<>\\|])*[^\\s\\\\/:\\*\\?\\\"<>\\|\\.]$");
    }
  }

  /**
   * 根据指定文件名，获取zip文件下该文件的内容
   *
   * @param zipFilePath    zip文件路径
   * @param targetFileName 文件名
   * @return 文件内容
   */
  @SuppressWarnings("unchecked")
  public static String readFileFromZipByName(String zipFilePath, String targetFileName) {
    File file = new File(zipFilePath);
    if (!file.exists()) {
      return null;
    }
    ZipFile zipFile = null;
    StringBuffer result = new StringBuffer();
    try {
      zipFile = new ZipFile(zipFilePath);
      Enumeration<ZipEntry> enu = (Enumeration<ZipEntry>) zipFile.entries();
      while (enu.hasMoreElements()) {
        ZipEntry zipElement = (ZipEntry) enu.nextElement();
        String srcFileName = zipElement.getName();
        if (srcFileName.contains(File.separator)) {
          srcFileName = srcFileName.substring(srcFileName.lastIndexOf(File.separator) + 1);
        }

        if (srcFileName.endsWith(targetFileName)) {
          BufferedReader br = null;
          String line;
          try {
            br = new BufferedReader(new InputStreamReader(zipFile.getInputStream(zipElement), "utf-8"));
            while ((line = br.readLine()) != null) {
              result.append(line);
            }
          } catch (Exception e) {
            e.printStackTrace();
          } finally {
            if (br != null) {
              br.close();
            }
          }
          break;
        }
      }
      return result.toString();
    } catch (Exception e) {
      e.printStackTrace();
      return null;
    } finally {
      if (zipFile != null) {
        try {
          zipFile.close();
        } catch (IOException e) {
          e.printStackTrace();
        }
      }
    }
  }

  /**
   * 根据文件类型获取zip文件夹下文件内容
   *
   * @param zipFilePath zip文件路径
   * @param type        zip文件路径
   * @return zip文件内容
   */
  @SuppressWarnings("unchecked")
  public static String readFileFromZipByType(String zipFilePath, String type) {
    File file = new File(zipFilePath);
    if (!file.exists()) {
      return null;
    }
    ZipFile zipFile = null;
    StringBuffer result = new StringBuffer();
    try {
      zipFile = new ZipFile(zipFilePath);
      Enumeration<ZipEntry> enu = (Enumeration<ZipEntry>) zipFile.entries();
      while (enu.hasMoreElements()) {
        ZipEntry zipElement = (ZipEntry) enu.nextElement();
        String srcFileName = zipElement.getName();
        String srcType = srcFileName.substring(srcFileName.lastIndexOf(".") + 1);
        if (srcType.equals(type)) {
          BufferedReader br = null;
          String line;
          try {
            br = new BufferedReader(new InputStreamReader(zipFile.getInputStream(zipElement), "utf-8"));
            while ((line = br.readLine()) != null) {
              result.append(line);
            }
          } catch (Exception e) {
            e.printStackTrace();
          } finally {
            if (br != null) {
              br.close();
            }
          }
          break;
        }
      }
      return result.toString();
    } catch (Exception e) {
      e.printStackTrace();
      return null;
    } finally {
      if (zipFile != null) {
        try {
          zipFile.close();
        } catch (IOException e) {
          e.printStackTrace();
        }
      }
    }
  }

//  /**
//   * 从指定的zip文件中读取文件
//   *
//   * @param zipFilePath    zip文件路径
//   * @param targetFileName 指定的zip文件中的文件名
//   * @return MultipartFile
//   */
//  @SuppressWarnings("unchecked")
//  public static MultipartFile readStream2File(String zipFilePath, String targetFileName) {
//    // 获得zip信息
//    try (ZipFile zipFile = new ZipFile(zipFilePath);) {
//
//      Enumeration<ZipEntry> enu = (Enumeration<ZipEntry>) zipFile.entries();
//      MultipartFile mockMultipartFile = null;
//      while (enu.hasMoreElements()) {
//        ZipEntry zipElement = (ZipEntry) enu.nextElement();
//        try (InputStream read = zipFile.getInputStream(zipElement);) {
//          String fileName = zipElement.getName();
//          if (fileName.contains(File.separator)) {
//            fileName = fileName.substring(fileName.lastIndexOf(File.separator) + 1);
//          }
//          if (fileName.endsWith(targetFileName)) {
//            mockMultipartFile = new MockMultipartFile(targetFileName, read);
//            break;
//          }
//        }
//      }
//      return mockMultipartFile;
//    } catch (Exception e) {
//      e.printStackTrace();
//    }
//    return null;
//  }

  /**
   * 根据指定文件夹，返回该文件夹下所有文件
   *
   * @param zipFilePath zip文件路径
   * @param dir         指定文件路径
   * @return 文件列表
   */
  @SuppressWarnings("unchecked")
  public static List<String> readFileListByDir(String zipFilePath, String dir) {
    List<String> result = new ArrayList<String>();
    File file = new File(zipFilePath);
    if (!file.exists()) {
      return result;
    }
    ZipFile zipFile = null;
    try {
      zipFile = new ZipFile(zipFilePath);
      Enumeration<ZipEntry> enu = (Enumeration<ZipEntry>) zipFile.entries();
      while (enu.hasMoreElements()) {
        ZipEntry zipElement = (ZipEntry) enu.nextElement();
        String srcFileName = zipElement.getName();
        if (srcFileName.contains(File.separator) && srcFileName.contains(dir)) {
          srcFileName = srcFileName.substring(srcFileName.lastIndexOf(File.separator) + 1);
          result.add(srcFileName);
        }
      }
    } catch (Exception e) {
      e.printStackTrace();
    } finally {
      if (zipFile != null) {
        try {
          zipFile.close();
        } catch (IOException e) {
          e.printStackTrace();
        }
      }
    }
    return result;
  }

  /**
   * 根据指定规则，返回zip包中的文件列表信息
   *
   * @param zipFilePath zip文件路径
   * @param patternRule 正则表达式
   * @return zip下文件集合
   */
  @SuppressWarnings("unchecked")
  public static List<String> readFileListByPatternRule(String zipFilePath, String patternRule) {
    List<String> result = new ArrayList<String>();
    File file = new File(zipFilePath);
    if (!file.exists()) {
      return result;
    }
    ZipFile zipFile = null;
    Pattern pattern = Pattern.compile(patternRule);
    try {
      zipFile = new ZipFile(zipFilePath);
      Enumeration<ZipEntry> enu = (Enumeration<ZipEntry>) zipFile.entries();
      while (enu.hasMoreElements()) {
        ZipEntry zipElement = (ZipEntry) enu.nextElement();
        String srcFileName = zipElement.getName();
        if (srcFileName.contains(File.separator)) {
          srcFileName = srcFileName.substring(srcFileName.lastIndexOf(File.separator) + 1);
        }
        if (srcFileName.contains("\\")) {
          srcFileName = srcFileName.substring(srcFileName.lastIndexOf("\\") + 1);
        }
        if (pattern.matcher(srcFileName).matches()) {
          result.add(srcFileName);
        }
      }
    } catch (Exception e) {
      e.printStackTrace();
    } finally {
      if (zipFile != null) {
        try {
          zipFile.close();
        } catch (IOException e) {
          e.printStackTrace();
        }
      }
    }
    return result;
  }
}
